﻿/*
摘要：OOCSS解析器
作者：李魁友
最后修改：2008-10-14
交流：QQ 66047391，QQ群 15774494
*/


Array.prototype.__IndexOf = function(value)
{
    for (var i = 0; i < this.length; i++)
    {
        if (this[i] == value)
        {
            return i;
        }
    }
    return -1;
}

RegExp.prototype.test = function(str)
{
    if (str)
        return str.search(this) > -1;
    else
        return false;
}

String.prototype.Trim = function()
{
    return this.replace(/(^\s+)|(\s+$)/g, "");
}

String.prototype.Int = function(errOrNullValue)
{
    var i = parseInt(this);
    return i == undefined ? errOrNullValue : i;
}

String.prototype.Float = String.prototype.Value = function(errOrNullValue)
{
    var f = parseFloat(this);
    return f == undefined ? errOrNullValue : f;
}

window.MyCookie =
{
    GetCookie: function(name)
    {
        var start = document.cookie.indexOf(name + "=");
        var len = start + name.length + 1;
        if ((!start) && (name != document.cookie.substring(0, name.length)))
        {
            return null;
        }
        if (start == -1)
            return null;
        var end = document.cookie.indexOf(';', len);
        if (end == -1)
            end = document.cookie.length;
        return unescape(document.cookie.substring(len, end));
    },

    SetCookie: function(name, value, expires, path, domain, secure)
    {
        var today = new Date();
        today.setTime(today.getTime());
        if (expires)
        {
            expires = expires * 1000 * 60 * 60 * 24;
        }

        var expires_date = new Date(today.getTime() + (expires));
        var cookie = name + '=' + escape(value) + ((expires) ? ';expires=' + expires_date.toGMTString() : '') +
        ((path) ? ';path=' + path : '') +
        ((domain) ? ';domain=' + domain : '') +
        ((secure) ? ';secure' : '');
        document.cookie = cookie
    },

    DeleteCookie: function(name, path, domain)
    {
        if (getCookie(name))
            document.cookie = name + '=' + ((path) ? ';path=' + path : '') + ((domain) ? ';domain=' + domain : '') + ';expires=Thu, 01-Jan-1970 00:00:01 GMT';
    }
}

//默认缓存到Cookie
window.CssCacheType = window.CssCacheType == null ? 'COOKIE' : window.CssCacheType;
window.CssCache = { keys: {} }
window.CssCache.GetCacheWin = function(win, isFirst)
{
    if (isFirst != false)
    {
        if (!CssCache.cacheWin)
        {
            CssCache.cacheWin = CssCache.GetCacheWin(win, false);
        }
        return CssCache.cacheWin;
    }

    try
    {
        if (win.top.AllCssCache)
        {
            return win.top;
        }
        else
        {
            var pTop = win.top.opener ? win.top.opener : win.dialogArguments;
            if (pTop && pTop.closed == false)
            {
                pTop = CssCache.GetCacheWin(pTop, false);
                if (pTop.AllCssCache)
                {
                    return pTop
                }
            }
        }
    } catch (e) { }
    return win.top;
}

CssCache.GetAllCssCache = function()
{
    var win = CssCache.GetCacheWin(window);
    var allCache = win.AllCssCache;
    if (allCache == null)
    {
        allCache = win.AllCssCache = {};
    }
    return allCache;
}


CssCache.GetSheetCacheKey = function(sheet)
{
    if ((!sheet.owningElement) || (!sheet.owningElement.href))
    {
        return "";
    }

    var cacheKey = sheet.owningElement.href.Trim();
    if (CssCache.keys[cacheKey])
    {
        return CssCache.keys[cacheKey];
    }
    if (!(cacheKey.substring(0, 1) == "/" || cacheKey.indexOf(':') > -1))
    {
        cacheKey = location.href.replace(/[^\/]*$/g, "") + cacheKey;
        while (cacheKey.indexOf("../") > -1)
        {
            cacheKey = cacheKey.replace(/[^\/]*\/\.{2}\//g, "");
        }
    }

    var pIndex = cacheKey.indexOf('?');
    if (pIndex > -1)
    {
        cacheKey = cacheKey.substring(0, pIndex + 1).toLowerCase() + cacheKey.substring(pIndex);
    }
    cacheKey = { key: cacheKey.Trim(), version: 0 };
    //cacheKey ={key: cacheKey.Trim(),version:sheet.cssText.length};
    return CssCache.keys[sheet.owningElement.href.Trim()] = cacheKey;
}

CssCache.GetSheetCache = function(sheet)
{
    var key = CssCache.GetSheetCacheKey(sheet);
    if (!key)
    {
        return null;
    }

    var cacheData = null;
    if (window.CssCacheType == "COOKIE")
    {
        cacheData = MyCookie.GetCookie(key.key);
    }
    else
    {
        cacheData = CssCache.GetAllCssCache()[key.key];
    }

    if (cacheData)
    {
        var index = cacheData.indexOf('|');
        if (index > -1)
        {
            if (cacheData.substring(0, index) == key.version)
            {
                cacheData = cacheData.substring(index + 1);
            }
            else
            {
                cacheData = null;
            }
        }
    }
    return cacheData;
}

CssCache.SetSheetCache = function(sheet, cacheData)
{
    var key = CssCache.GetSheetCacheKey(sheet);
    if (!key)
    {
        return;
    }

    cacheData = key.version + "|" + cacheData;
    if (window.CssCacheType == "COOKIE")
    {
        MyCookie.SetCookie(key.key, cacheData, 7, "", location.host);
    }
    else
    {
        CssCache.GetAllCssCache()[key.key] = cacheData;
    }
}


//默认情况不处理脚本后的CSS
window.AFTEROFF = window.AFTEROFF == null ? true : window.AFTEROFF;
//默认开启缓存
window.CSSCACHEOFF = window.CSSCACHEOFF == null ? false : window.CSSCACHEOFF;
if (true || location.host.charAt(0) == "1" || location.host == "localhost")
{
    window.CSSCACHEOFF = true
}

window.CssInterpreter =
{
    HtmlTags: "|TITLE|ISINDEX|META|LINK|BASE|SCRIPT|STYLE|NEXTID|H1|H2|H3|H4|H5|H6|UL|OL|DIR|MENU|DL|P|PRE|BLOCKQUOTE|DIV|CENTER|FORM|HR|TABLE|ADDRESS|NOSCRIPT|EM|STRONG|DFN|CODE|SAMP|KBD|VAR|CITE|TT|I|B|U|STRIKE|BIG|SMALL|SUB|SUP|A|BASEFONT|IMG|APPLET|FONT|BR|MAP|NOBR|BLINK|S|Q|ABBR|ACRONYM|SPAN|DEL|INS|IFRAME|OBJECT|LI|DT|DD|INPUT|SELECT|TEXTAREA|OPTION|CAPTION|THEAD|TFOOT|TR|TH|TD|AREA|PARAM|HTML|HEAD|BODY|FRAMESET|FRAME|NOFRAMES|PLAINTEXT|SANS|LISTING|FUPPLET|MULTICOL|",
    WithAttribute: "event",
    WithAttributeAutoValue: "''",
    BaseNotFindHint: "错误: 样式 {0} 的基类 {1} 未找到 ;",
    NoHtmlTagWarning: '警告: 样式 {0} 的基类 {1} 不是正确的HTML标签,请在基类名称前加 "." ;',
    ParsedStyleSheetCount: 0,
    DeferApplyBaseRules: new Array(),
    SheetDatas: {},
    Rules: new Array(),
    BaseWordReg: /\bbase\b/g,
    BasesWordReg: /\bbases\b/g,
    BaseRuleReg: /\bbase\s*:\s*([^;]*)/gi,
    AppendRuleReg: /\bappend\s*:\s*([^;]*)/gi,
    MeWordReg: /\bme\b/g,
    BaseMeWordReg: /\b(base|bases|me)\b/g,
    ExpressionReg: /\b([\w-#\*]+)\s*:\s*expression\s*\(/ig,
    EvalReg: /\bE-([\w-#\*]+)\s*:\s*eval\s*\(([^;]*)\)/ig,
    AttributeReg: /\b([\w-#\*]+\s*):/g,
    CustomAttributeReg: /\bE-[\w-#\*]+\s*:/gi,
    RuleReg: /[^\}]?([\.#:\s\w-\*]+)\s*\{([^\}]*)\}/g,
    GlobalRuleReg: /\.global\s*$/i,
    BasesKeyIndexReg: new RegExp("\\bbases\\s*\\[\\s*[\\'\\\"].*[\\'\\\"]\\s*\\]", "g"),
    StartKeyIndex: 0,
    DoubleQuot: "ω ",
    SingleQuot: "╯",
    BigBracketBegin: "♭",
    BigBracketEnd: "♩",
    SmallBracketBegin: "≤",
    SmallBracketEnd: "≥",
    Msg: "",
    TestElement: document.createElement("span"),
    isIE: window.navigator.appName.indexOf("Internet Explorer") > -1,
    GetUniqueKey: function(prefix)
    {
        CssInterpreter.StartKeyIndex++;
        return prefix + "_" + CssInterpreter.StartKeyIndex
    }
}

CssInterpreter.Sheet = function(sheet, sheetIndex)
{
    var me = this;
    me.sheet = sheet;
    me.sheetIndex = sheetIndex;
    if (!CssInterpreter.isIE)
    {
        me.innerHTML = sheet.ownerNode.innerHTML;
        //替换\\"或\\'(字符串里面的引号)
        var html = me.innerHTML.replace(new RegExp("\\\\\"", "g"), "\\\\" + CssInterpreter.DoubleQuot).replace(new RegExp('\\\\\'', "g"), "\\\\" + CssInterpreter.SingleQuot);
        //处理字符串中的括号
        var matchs = html.match(new RegExp('(\\"[^\\"]*\\")|(\\\'[^\\\']*\\\')', "g"));
        if (matchs)
        {
            for (var m = 0; m < matchs.length; m++)
            {
                var str = matchs[m];
                str = str.replace(/\(/g, CssInterpreter.SmallBracketBegin).replace(/\)/g, CssInterpreter.SmallBracketEnd).replace(/\{/g, CssInterpreter.BigBracketBegin).replace(/\}/g, CssInterpreter.BigBracketEnd);
                if (matchs[m] != str)
                {
                    html = html.replace(matchs[m], str);
                }
            }
        }

        matchs = html.match(CssInterpreter.ExpressionReg);
        if (matchs)
        {
            for (var m = 0; m < matchs.length; m++)
            {
                var str = matchs[m];
                str.match(CssInterpreter.ExpressionReg);
                var ruleName = RegExp.$1;
                str = "E-" + ruleName + str.replace(/.*:\s*expression\b/gi, ":eval");
                html = html.replace(matchs[m], str);
            }
        }

        html = html.replace(/\s+/g, " ");
        me.cssText = html;
        me.rules = new Array();
        var cssRules = sheet.cssRules;

        matchs = me.cssText.match(CssInterpreter.RuleReg);
        if (matchs)
        {
            for (var m = 0; m < matchs.length; m++)
            {
                var str = "";
                if (matchs.length > m + 1)
                {
                    var nextIndex = html.indexOf(matchs[m + 1]);
                    str = html.substr(0, nextIndex);
                    html = html.substr(nextIndex);
                }
                else
                {
                    str = html;
                }

                str.match(CssInterpreter.RuleReg);
                var ruleName = RegExp.$1.Trim();
                var cssRule = cssRules[m];
                if (cssRule.selectorText == ruleName)
                {
                    var rule = {};
                    me.rules.push(rule);
                    rule.cssRule = cssRule
                    rule.style = rule.cssRule.style;
                    rule.selectorText = rule.cssRule.selectorText;
                    rule.cssText = str.replace(/^([^\{]*{)|}([^\}]*)$/g, "");
                    //alert(rule.cssText)
                    rule.cssText = rule.cssText.replace(CssInterpreter.SmallBracketBegin, "(").replace(CssInterpreter.SmallBracketEnd, ")").replace(CssInterpreter.BigBracketBegin, "{").replace(CssInterpreter.BigBracketEnd, "}").replace(CssInterpreter.DoubleQuot, '"').replace(CssInterpreter.SingleQuot, "'");
                    //alert(rule.cssText)
                    if (CssInterpreter.BaseRuleReg.test(str))
                    {
                        rule.style["base"] = RegExp.$1;
                        //alert(rule.style["base"])
                    }

                    if (CssInterpreter.AppendRuleReg.test(str))
                    {
                        rule.style["append"] = RegExp.$1;
                        //alert(rule.style["append"])
                    }
                }
            }
        }
    }
    else
    {
        me.innerHTML = sheet.cssText;
        me.rules = me.sheet.rules;
    }
}

CssInterpreter.Rule = function(sheet, rule, sheetIndex, ruleIndex, sheetCacheChangedIndexs)
{
    var me = this;
    me.selectorText = rule.selectorText.Trim().toLowerCase();
    me.Rule = rule;
    me.style = rule.style;
    CssInterpreter.Rules.push(me);

    //    me.SheetIndex = sheetIndex;
    //    me.RuleIndex = ruleIndex        

    me.Sheet = sheet;
    CssInterpreter.SheetDatas[sheetIndex].push(me)

    if (sheetCacheChangedIndexs)
    {
        me.needParse = sheetCacheChangedIndexs.indexOf("," + ruleIndex + ",") > -1;
    }
    else
    {
        me.needParse = true;
    }

    if (me.needParse)
    {
        me.BaseAttribute = me.style["base"];
        me.AppendAttribute = me.style["append"];

        if (me.BaseAttribute)
        {
            me.BaseAttribute = me.BaseAttribute.toLowerCase();
        }

        if (me.selectorText == ".global" || me.selectorText == ".init")
        {
            CssInterpreter.ParseEval(me);
        }
    }
}

if (CssInterpreter.isIE)
{
    CssInterpreter.Rule.prototype.GetCssText = function()
    {
        if (this.cssText == null)
        {
            this.cssText = this.style.cssText;
        }
        return this.cssText;
    }
}
else
{
    CssInterpreter.Rule.prototype.GetCssText = function()
    {
        if (this.cssText == null)
        {
            this.cssText = this.Rule.cssText;
        }
        return this.cssText;
    }
}

CssInterpreter.Rule.prototype.SetCssText = function(cssText)
{
    if (this.cssText != cssText)
    {
        this.cssText = cssText;
        this.edited = true
    }
};
CssInterpreter.Rule.prototype.Update = function()
{
    if (this.edited && this.cssText != this.style.cssText)
    {
        this.Sheet.realChanged = true;
        this.realChanged = true;
        this.style.cssText = this.cssText;
    }
    this.edited = false;
}

CssInterpreter.Rule.prototype.GetKey = function()
{
    if (!this.key)
    {
        this.key = CssInterpreter.GetUniqueKey("_rule");
        window[this.key] = this.style;
    }
    return this.key;
}

CssInterpreter.Rule.prototype.GetBasesKey = function()
{
    if (!this.basesKey)
    {
        this.baseStyles = new Array();
        this.basesKey = CssInterpreter.GetUniqueKey("_bases");
        window[this.basesKey] = this.baseStyles;
    }

    if (this.baseStyles.length < this.Bases.length)
    {
        for (var b = this.baseStyles.length; b < this.Bases.length; b++)
        {
            this.baseStyles.push(this.Bases[b].style);
        }
    }

    return this.basesKey;
}

CssInterpreter.Rule.prototype.RegisterDeferApplyBase = function(baseName)
{
    var me = this;
    if (CssInterpreter.DeferApplyBaseRules.__IndexOf(me) < 0)
    {
        CssInterpreter.DeferApplyBaseRules.push(me);
    }

    if (!me.DeferApplyBaseRuleNames)
    {
        me.DeferApplyBaseRuleNames = new Array();
    }

    if (me.DeferApplyBaseRuleNames.__IndexOf(baseName) < 0)
    {
        me.DeferApplyBaseRuleNames.push(baseName);
    }
}

CssInterpreter.Rule.prototype.ParseExpression = function(cssText)
{
    var me = this;
    if (CssInterpreter.BaseMeWordReg.test(cssText) && (CssInterpreter.ExpressionReg.test(cssText) || CssInterpreter.EvalReg.test(cssText)))
    {
        if (CssInterpreter.BasesWordReg.test(cssText))
        {
            //将对基类用键的替换成用索引的访问
            if (CssInterpreter.BasesKeyIndexReg.test(cssText))
            {
                var baseNames = me.BaseNames.split(",");
                var matchs = cssText.match(CssInterpreter.BasesKeyIndexReg);
                for (var m = 0; m < matchs.length; m++)
                {
                    var name = matchs[m].replace(new RegExp("(.*\\[)|(\\].*)|[\\s\\'\\\"]", "g"), "");
                    var index = baseNames.__IndexOf(name.Trim().toLowerCase());
                    if (index > -1)
                    {
                        cssText = cssText.replace(matchs[m], "bases[" + index + "]");
                    }
                }
            }
            cssText = cssText.replace(CssInterpreter.BasesWordReg, me.GetBasesKey());
        }

        if (/(base\s*:\s*[^;]*;?)/gi.test(cssText))
        {
            cssText = cssText.replace(RegExp.$1, RegExp.$1.replace(/base/i, "BASE"));
        }

        try
        {
            cssText = cssText.replace(CssInterpreter.BaseWordReg, me.Bases[0].GetKey())
        } catch (e) { }
        try
        {
            cssText = cssText.replace(CssInterpreter.MeWordReg, me.GetKey());
        } catch (e) { }


    }
    return cssText;
}

CssInterpreter.SetCssAppend = function(element, base)
{
    if (!element.setCssAppended)
    {
        element.className += " " + base.replace(/(\.|,)+/g, " ");
        element.setCssAppended = true;
        element.runtimeStyle.cssText = element.runtimeStyle.cssText + ";" + CssInterpreter.WithAttribute + ":expression(" + CssInterpreter.WithAttributeAutoValue + ")";
    }

}

CssInterpreter.ApplyBase = function(cssRule, baseName)
{
    var baseRule = CssInterpreter.FindRule(baseName);
    if (baseRule == null)
    {
        if (/^\s*\w/.test(baseName) && CssInterpreter.HtmlTags.indexOf("|" + baseName.toUpperCase().replace(/\s/g, "") + "|") < 0)
        {
            baseRule = CssInterpreter.FindRule("." + baseName);
            if (baseRule && CssInterpreter.NoHtmlTagWarning)
            {
                CssInterpreter.Msg += CssInterpreter.NoHtmlTagWarning.replace('{0}', cssRule.selectorText).replace('{1}', baseName);
            }
        }
    }

    if (baseRule == null)
    {
        //假如是第一阶段分析
        if (CssInterpreter.ParsedStyleSheetCount < 1)
        {
            cssRule.RegisterDeferApplyBase(baseName);
        }
        else if (CssInterpreter.BaseNotFindHint)
        {
            CssInterpreter.Msg += CssInterpreter.BaseNotFindHint.replace('{0}', cssRule.selectorText).replace('{1}', baseName);
        }
    }
    else
    {
        //假如在分析基类时出错且是第一阶段分析,则延迟
        if (CssInterpreter.ParseBase(baseRule) == false && CssInterpreter.ParsedStyleSheetCount < 1)
        {
            cssRule.RegisterDeferApplyBase(baseName);
        }
        else
        {
            CssInterpreter._applyBase(cssRule, baseRule);
            return true;
        }
    }

    return false;
}

CssInterpreter._applyBase = function(cssRule, baseRule)
{
    var bases = cssRule.Bases;
    if (!bases)
    {
        bases = new Array()
        cssRule.Bases = bases;
        cssRule.BaseNames = "";
    }

    //避免重复继承
    if (cssRule.BaseNames.indexOf(baseRule.selectorText) > -1)
    {
        return;
    }

    bases.push(baseRule);
    if (cssRule.BaseNames != "")
        cssRule.BaseNames += ","
    cssRule.BaseNames += baseRule.selectorText;

    var childs = baseRule.Childs;
    if (!childs)
    {
        childs = new Array();
        baseRule.Childs = childs;
        baseRule.ChildNames = "";
    }
    childs.push(cssRule);
    if (baseRule.ChildNames != "")
        baseRule.ChildNames += ","
    baseRule.ChildNames += cssRule.selectorText;

    cssRule.SetCssText(cssRule.ParseExpression(baseRule.style.cssText + ";" + cssRule.GetCssText()));
}

CssInterpreter.ParseBase = function(cssRule)
{
    //所有基类已经正确应用
    if (cssRule["applyAllBase"])
    {
        return true
    }
    //假如此阶段已经分析过但应用基类有误
    else if (cssRule["parsed" + CssInterpreter.ParsedStyleSheetCount])
    {
        return false;
    }

    cssRule["parsed" + CssInterpreter.ParsedStyleSheetCount] = true;

    var baseNames = cssRule.BaseAttribute;
    var returnValue = true;
    if (baseNames)
    {
        baseNames = baseNames.replace(/( |,)+/g, ",").split(",");
        for (var n = 0; n < baseNames.length; n++)
        {
            //假如应用基类时出错
            if (!CssInterpreter.ApplyBase(cssRule, baseNames[n]))
            {
                returnValue = false;
            }
        }
    }
    cssRule["applyAllBase"] = returnValue;
    return returnValue;
}

CssInterpreter.ApplyAppend = function(cssRule, appendCssNames)
{
    cssRule.SetCssText(cssRule.GetCssText() + ";" + CssInterpreter.WithAttribute + " :expression(CssInterpreter.SetCssAppend(this,'" + appendCssNames + "'));");
}

CssInterpreter.FindRule = function(ruleName)
{
    var trimReg = /(^ *)|( *$)/i;
    ruleName = ruleName.toLowerCase().replace(trimReg, "");
    for (var i = 0; i < CssInterpreter.Rules.length; i++)
    {
        var rule = CssInterpreter.Rules[i];
        if (rule.selectorText == ruleName)
        {
            return rule;
        }
    }
}


CssInterpreter.ParseEval = function(cssRule)
{
    var cssText = cssRule.GetCssText();

    //避免有 me 的情况
    cssText = cssRule.ParseExpression(cssText);

    if (CssInterpreter.EvalReg.test(cssText))
    {
        var matchs = cssText.match(CssInterpreter.EvalReg);
        for (var m = 0; m < matchs.length; m++)
        {
            //CssInterpreter.EvalReg.test(matchs[m]);
            var attStr = matchs[m]
            CssInterpreter.EvalReg.test(attStr);
            var expression = RegExp.$2;
            var name = RegExp.$1;
            var value = '';
            try
            {
                value = eval(expression);
            } catch (e) { }

            if (typeof (value) == "function" || typeof (value) == "object")
            {
                value = "";
            }

            cssText = cssText.replace(matchs[m], name + ":" + value);
        }
    }

    if (CssInterpreter.CustomAttributeReg.test(cssText))
    {
        var matchs = cssText.match(CssInterpreter.CustomAttributeReg);
        for (var m = 0; m < matchs.length; m++)
        {
            /E-([\w-]*)\s*:/gi.test(matchs[m]);
            var name = RegExp.$1;
            cssText = cssText.replace(matchs[m], name + ":");
        }
    }

    cssRule.SetCssText(cssText);
    return
}

CssInterpreter.Parse = function(defer)
{
    var baseOn = !window.BASEOFF;
    var appendOn = !window.APPENDOFF;
    var evalOn = !window.EVALOFF;

    if (!(baseOn || appendOn || evalOn))
    {
        return;
    }

    var parsedCount = CssInterpreter.Rules.length;

    for (var s = CssInterpreter.ParsedStyleSheetCount; s < document.styleSheets.length; s++)
    {
        var sheet = CssInterpreter.isIE ? document.styleSheets[s] : new CssInterpreter.Sheet(document.styleSheets[s], s);
        var rules = sheet.rules;
        CssInterpreter.SheetDatas[s] = new Array();

        var off = sheet.owningElement.getAttribute("ooCssOff");
        if (off != null)
        {
            off = off.Trim().toLowerCase();
            if (off == "1" || off == "true" || off == "off")
            {
                continue;
            }
        }

        var cacheChangedIndexs = null;
        if (!window.CSSCACHEOFF)
        {
            cacheChangedIndexs = CssCache.GetSheetCache(sheet);
        }

        for (var r = 0; r < rules.length; r++)
        {
            var rule = new CssInterpreter.Rule(sheet, rules[r], s, r, cacheChangedIndexs);
        }
    }

    var rules = CssInterpreter.Rules;
    var c = 0;
    for (var i = parsedCount; i < rules.length; i++)
    {
        var rule = rules[i];

        if (rule.needParse == false)
        {
            continue;
        }
        c++;
        if (baseOn && rule.AppendAttribute)
        {
            CssInterpreter.ApplyAppend(rule, rule.AppendAttribute);
        }

        var baseParseEnd = true;
        if (appendOn && rule.BaseAttribute)
        {
            baseParseEnd = CssInterpreter.ParseBase(rule);
        }

        if (evalOn && baseParseEnd)
        {
            CssInterpreter.ParseEval(rule);
        }

        rule.Update();
    }

    //alert(c + ";" + (rules.length-parsedCount));

    CssInterpreter.ParsedStyleSheetCount = document.styleSheets.length;
}

CssInterpreter.ParseDeferApplyBase = function()
{
    for (var i = 0; i < CssInterpreter.DeferApplyBaseRules.length; i++)
    {
        var rule = CssInterpreter.DeferApplyBaseRules[i];
        for (var n = 0; n < rule.DeferApplyBaseRuleNames.length; n++)
        {
            CssInterpreter.ApplyBase(rule, rule.DeferApplyBaseRuleNames[n]);
        }

        if (!window.EVALOFF)
        {
            CssInterpreter.ParseEval(rule);
        }

        rule.Update();
    }
}

document.attachEvent("onreadystatechange", function()
{
    if (document.readyState == "complete")
    {
        var d = new Date();
        if (!window.AFTEROFF)
        {
            CssInterpreter.Parse(true);
            window.setTimeout("CssInterpreter.Parse(true)", 20);
        }

        window.setTimeout(CssInterpreter.ParseDeferApplyBase, 50);

        if (!window.CSSCACHEOFF)
        {
            window.setTimeout(function()
            {
                for (var s = 0; s < document.styleSheets.length; s++)
                {
                    var sheet = document.styleSheets[s];
                    if (sheet.owningElement && sheet.owningElement.href)
                    {
                        var cacheData = CssCache.GetSheetCache(sheet);
                        if (cacheData == null)
                        {
                            if (sheet.realChanged)
                            {
                                cacheData = "";
                                var rules = CssInterpreter.SheetDatas[s];
                                for (var r = 0; r < rules.length; r++)
                                {
                                    if (rules[r].realChanged)
                                    {
                                        cacheData += "," + r;
                                    }
                                }
                                cacheData += ","
                            }
                            else
                            {
                                cacheData = "-1";
                            }

                            CssCache.SetSheetCache(sheet, cacheData);
                        }
                    }
                }
            }, 100);
        }



        if (CssInterpreter.Msg == "")
        {
            if (location.host.charAt(0) == "1" || location.host.charAt(0) == "l")
            {
                window.status += "  CSS解析耗时  " + beforeTime + " + " + (new Date() - d) + " 毫秒";
            }
        }
        else
        {
            window.status = CssInterpreter.Msg;
        }

        //        if (window._alert)
        //            _alert(new Date() - d);
        //        else
        //            alert(new Date() - d);

    }
});

var d = new Date();
CssInterpreter.Parse();
var beforeTime = new Date() - d;


//if(window._alert)
//    _alert(new Date() - d);
//else
//    alert(new Date() - d);


window.onunload = function()
{
    CssInterpreter.Rules = null;
    CssInterpreter = null;
}